# Scores for a 9-hole round
scores = [4, 5, 3, 6, 4, 3, 5, 4, 5]
# Accessing elements (0-indexed)
print(f"Hole 1 score: {scores[0]}")
print(f"Last hole score: {scores[-1]}")
# Slicing
front_3 = scores[:3]
back_3 = scores[-3:]
print(f"First 3 holes: {front_3}")
print(f"Last 3 holes: {back_3}")Data Types, Decisions, and Loops
This notebook covers the core building blocks of Python: data structures, conditional logic, and iteration. Every example uses golf data.
What You’ll Learn
- Lists, tuples, and dictionaries — when to use each
- Boolean logic and comparison operators
if/elif/elsedecision structuresforandwhileloops- Putting it all together to analyze a round of golf
Concept: Organizing Data
Programs need to store collections of data. Python has three main built-in collection types:
| Type | Syntax | Mutable? | Use Case |
|---|---|---|---|
| List | [4, 3, 5] |
Yes | Ordered, changeable collections (hole scores, shot distances) |
| Tuple | (4, 385, 7) |
No | Fixed data that shouldn’t change (par, yardage, handicap index) |
| Dict | {"driver": 245} |
Yes | Key-value lookups (club distances, player stats) |
The key insight: use tuples for data that describes something fixed (a hole’s par never changes mid-round), lists for data that accumulates (scores build up as you play), and dicts for lookups (what club did I hit on hole 5?).
Code: Lists
Lists are ordered, mutable collections. You’ll use them constantly.
# Lists are mutable — you can change them
scores = [4, 5, 3, 6, 4, 3, 5, 4, 5]
# Oops, scored a 5 on hole 2, not 6
scores[3] = 5
print(f"Corrected scores: {scores}")
# Add a score (hole 10 if we keep playing)
scores.append(4)
print(f"After adding hole 10: {scores}")
# Useful list operations
print(f"Total: {sum(scores)}")
print(f"Holes played: {len(scores)}")
print(f"Best hole: {min(scores)}")
print(f"Worst hole: {max(scores)}")
print(f"Sorted: {sorted(scores)}")Code: Tuples
Tuples are like lists but immutable — once created, they can’t be changed. Use them for fixed data.
# A hole's characteristics never change during a round
# (hole_number, par, yardage, handicap_index)
hole_1 = (1, 4, 385, 7)
hole_2 = (2, 3, 165, 13)
hole_3 = (3, 5, 530, 3)
# Access by index
print(f"Hole {hole_1[0]}: Par {hole_1[1]}, {hole_1[2]} yards")
# Tuple unpacking — much more readable
hole_num, par, yardage, hcp_idx = hole_3
print(f"Hole {hole_num}: Par {par}, {yardage} yards (HCP {hcp_idx})")# Tuples are immutable — this will raise an error
hole_1 = (1, 4, 385, 7)
try:
hole_1[1] = 5 # Can't change par!
except TypeError as e:
print(f"Error: {e}")
print("Tuples can't be modified — that's the point!")# A list of tuples — common pattern for course data
course_holes = [
(1, 4, 385, 7),
(2, 3, 165, 13),
(3, 5, 530, 3),
(4, 4, 410, 1),
(5, 4, 370, 11),
(6, 3, 195, 15),
(7, 5, 545, 5),
(8, 4, 420, 9),
(9, 4, 395, 17),
]
total_par = sum(par for _, par, _, _ in course_holes)
total_yardage = sum(yds for _, _, yds, _ in course_holes)
print(f"Front 9: Par {total_par}, {total_yardage} yards")Code: Dictionaries
Dictionaries map keys to values. Perfect for lookups and structured data.
# Club distances (average carry in yards)
club_distances = {
"Driver": 245,
"3-Wood": 215,
"4-Hybrid": 195,
"5-Iron": 180,
"6-Iron": 170,
"7-Iron": 155,
"8-Iron": 140,
"9-Iron": 125,
"PW": 110,
"50°": 95,
"58°": 70,
}
# Lookup
print(f"7-Iron carries {club_distances['7-Iron']} yards")
# Check if a key exists
print(f"Has a 60° wedge? {'60°' in club_distances}")
# Safe lookup with .get()
distance = club_distances.get("60°", "unknown")
print(f"60° distance: {distance}")# A player's round as a dict
round_data = {
"player": "Bear Woods",
"course": "North Park Golf Course",
"date": "2024-03-15",
"scores": [4, 3, 5, 5, 4, 3, 6, 4, 4, 5, 3, 5, 5, 4, 3, 5, 4, 5],
"weather": "sunny",
}
print(f"{round_data['player']} at {round_data['course']}")
print(f"Total: {sum(round_data['scores'])}")
print(f"Weather: {round_data['weather']}")Concept: Making Decisions
Programs need to make choices. In golf terms: - Is this score a birdie, par, or bogey? - Did the player make the cut? - Should I hit driver or lay up?
Python uses if, elif, and else for decision logic, combined with boolean expressions that evaluate to True or False.
Code: Boolean Expressions and Comparisons
score = 3
par = 4
# Comparison operators
print(f"{score} == {par} → {score == par}") # Equal
print(f"{score} != {par} → {score != par}") # Not equal
print(f"{score} < {par} → {score < par}") # Less than
print(f"{score} <= {par} → {score <= par}") # Less than or equal
print(f"{score} > {par} → {score > par}") # Greater than# Combining with and, or, not
score = 68
par = 72
cut_line = 144 # 36-hole cut
day1_score = 70
day2_score = 73
two_day_total = day1_score + day2_score
under_par = score < par
made_cut = two_day_total <= cut_line
print(f"Under par today? {under_par}")
print(f"Made the cut? {made_cut}")
print(f"Under par AND made cut? {under_par and made_cut}")
print(f"Under par OR made cut? {under_par or made_cut}")
print(f"Missed cut? {not made_cut}")Code: if / elif / else
def scoring_name(score: int, par: int) -> str:
"""Return the golf name for a score on a hole."""
diff = score - par
if diff <= -3:
return "Albatross"
elif diff == -2:
return "Eagle"
elif diff == -1:
return "Birdie"
elif diff == 0:
return "Par"
elif diff == 1:
return "Bogey"
elif diff == 2:
return "Double Bogey"
else:
return "Triple Bogey+"
# Test it
test_cases = [(2, 4), (3, 4), (4, 4), (5, 4), (6, 4), (3, 5), (1, 3)]
for score, par in test_cases:
print(f"Score {score} on a par {par} = {scoring_name(score, par)}")# Nested decisions: club selection based on distance and conditions
distance_to_pin = 165
wind = "into" # "into", "with", "none"
lie = "fairway" # "fairway", "rough", "sand"
if lie == "sand":
club = "SW"
elif distance_to_pin > 200:
club = "3-Wood"
elif distance_to_pin > 150:
if wind == "into":
club = "5-Iron" # Club up for headwind
elif wind == "with":
club = "7-Iron" # Club down for tailwind
else:
club = "6-Iron"
else:
club = "8-Iron"
print(f"{distance_to_pin} yards, {lie} lie, wind {wind} → {club}")Concept: Iteration (Loops)
Loops let you repeat an action for each item in a collection or until a condition is met.
forloop — iterate over a known collection (holes, scores, players)whileloop — repeat until a condition changes (keep putting until holed out)
In data science, for loops are far more common. You’ll loop over rows, columns, files, and datasets constantly.
Code: for Loops
# Loop over scores to build a hole-by-hole summary
pars = [4, 3, 5, 4, 4, 3, 5, 4, 4]
scores = [4, 3, 6, 5, 4, 2, 5, 4, 5]
for i in range(len(scores)):
name = scoring_name(scores[i], pars[i])
print(f"Hole {i + 1}: {scores[i]} ({name})")# Better: use enumerate() for index + value
for i, (score, par) in enumerate(zip(scores, pars), start=1):
name = scoring_name(score, par)
diff = score - par
diff_str = f"{diff:+d}" if diff != 0 else " E"
print(f"Hole {i:2d}: {score} (par {par}) {diff_str:>3s} {name}")# Loop over a list of tuples — course data
course_holes = [
(1, 4, 385, 7), (2, 3, 165, 13), (3, 5, 530, 3),
(4, 4, 410, 1), (5, 4, 370, 11), (6, 3, 195, 15),
(7, 5, 545, 5), (8, 4, 420, 9), (9, 4, 395, 17),
]
par_3s = []
par_4s = []
par_5s = []
for hole_num, par, yardage, hcp in course_holes:
if par == 3:
par_3s.append(yardage)
elif par == 4:
par_4s.append(yardage)
else:
par_5s.append(yardage)
print(f"Par 3s: {par_3s} (avg {sum(par_3s)/len(par_3s):.0f} yards)")
print(f"Par 4s: {par_4s} (avg {sum(par_4s)/len(par_4s):.0f} yards)")
print(f"Par 5s: {par_5s} (avg {sum(par_5s)/len(par_5s):.0f} yards)")# Loop over a dictionary
club_distances = {
"Driver": 245, "3-Wood": 215, "5-Iron": 180,
"7-Iron": 155, "9-Iron": 125, "PW": 110,
}
print("Clubs that carry over 150 yards:")
for club, distance in club_distances.items():
if distance > 150:
print(f" {club}: {distance} yards")Code: while Loops
# Simulate putting until holed out
import random
random.seed(42)
distance_feet = 30 # Starting putt distance
putt_count = 0
while distance_feet > 0:
putt_count += 1
# Simulate: leave it roughly 20% of the remaining distance
remaining = distance_feet * random.uniform(0.05, 0.35)
if remaining < 1.0: # Inside 1 foot = holed
print(f" Putt {putt_count}: {distance_feet:.1f} ft → Holed!")
distance_feet = 0
else:
print(f" Putt {putt_count}: {distance_feet:.1f} ft → {remaining:.1f} ft remaining")
distance_feet = remaining
print(f"Total putts: {putt_count}")Code: Putting It All Together
Let’s combine everything to build a scorecard display.
# Complete scorecard builder
course_holes = [
(1, 4, 385), (2, 3, 165), (3, 5, 530), (4, 4, 410), (5, 4, 370),
(6, 3, 195), (7, 5, 545), (8, 4, 420), (9, 4, 395),
]
scores = [4, 3, 6, 5, 4, 2, 5, 4, 5]
print(f"{'Hole':>4s} {'Par':>3s} {'Yds':>4s} {'Score':>5s} {'vs Par':>6s} {'Name'}")
print("-" * 45)
running_total = 0
running_par = 0
for (hole_num, par, yardage), score in zip(course_holes, scores):
running_total += score
running_par += par
diff = score - par
diff_str = f"{diff:+d}" if diff != 0 else "E"
name = scoring_name(score, par)
print(f"{hole_num:4d} {par:3d} {yardage:4d} {score:5d} {diff_str:>6s} {name}")
print("-" * 45)
total_diff = running_total - running_par
total_str = f"{total_diff:+d}" if total_diff != 0 else "E"
print(f"{'OUT':>4s} {running_par:3d} {running_total:5d} {total_str:>6s}")AI: Decision Logic and Loops
Exercise 1: Let AI Build a Scorecard
Try this prompt:
“Write Python code that takes a list of pars and a list of scores for 18 holes. Print a formatted scorecard that shows each hole, par, score, the golf name (birdie, par, bogey, etc.), and a running total. Include front 9 and back 9 subtotals.”
Evaluate: - Does it handle the front 9 / back 9 split correctly? - Does it handle eagles and double bogeys? - How does the formatting compare to what we built above?
Exercise 2: Have AI Explain Code
Copy this line from our code above and ask AI to explain it:
for i, (score, par) in enumerate(zip(scores, pars), start=1):“Explain this Python line step by step. What does zip do? What does enumerate do? What does the tuple unpacking (score, par) do?”
This is one of the most valuable uses of AI — explaining unfamiliar syntax. It’s faster than searching docs and you can ask follow-up questions.
Exercise 3: Strategy Decision Tree
Try asking AI to build something more complex:
“Write a Python function that recommends a club based on: distance to pin (yards), lie (fairway/rough/sand), wind (into/with/none), and elevation change (uphill/downhill/flat). Use if/elif/else logic. Include type hints.”
Evaluate: Does the logic make golf sense? Would a real golfer agree with the recommendations?
# Paste and test AI-generated code hereSummary
- Lists
[4, 3, 5]— mutable, ordered; use for scores, distances, any changing collection - Tuples
(4, 385, 7)— immutable; use for fixed data like hole info (par, yardage) - Dicts
{"Driver": 245}— key-value pairs; use for lookups and structured data - if/elif/else — make decisions based on conditions
- for loops — iterate over collections;
enumerate()andzip()are your friends - while loops — repeat until a condition changes
Next up: Functions — building reusable golf tools.